/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	tcp_transfer.c
**  Description:	与上位机连接的传输层协议
**  Author:        	 
**  Version				v0.1
**  Date:           	20221017
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "os_config.h"
#include "tcp_transfer.h"
#include "system_cfg.h"
#include "crc16.h"



/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/
static void transfer_timer_callback(void* arg);
static void transfer_input(eth_msg_t event,uint8_t* buff,uint16_t size);
static void transfer_output(protocol_cmd_t cmd,uint32_t win,void* buff,uint16_t size);
static uint16_t transfer_crc(uint8_t* buff);
/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/

static rt_timer_t transfer_timer;
static uint8_t __attribute__((aligned(4))) rt_transfer_mp_buff[RT_MEMPOOL_BYTE_SIZE(TRANSFER_SEND_LIST_MAX,sizeof(transfer_send_node_t))];
static transfer_cb_t transfer_handle;
/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/

transfer_err_t tcp_transfer_init(void)
{
	eth_tcp_cb_reg(transfer_input);
	memset(&transfer_handle,0,sizeof(transfer_handle));
	if(RT_EOK != rt_mp_init(&transfer_handle.transfer_send_mem,
		"transfer mem pool",
		rt_transfer_mp_buff,
		RT_MEMPOOL_BYTE_SIZE(TRANSFER_SEND_LIST_MAX,sizeof(transfer_send_node_t)),
		sizeof(transfer_send_node_t)
		))
	{
		Critical_Log("transfer mem create failed!\r\n");
	}
	transfer_timer = rt_timer_create("transfer timer",transfer_timer_callback,RT_NULL,TRANSFER_PERIODIIC_INTERVAL,RT_TIMER_FLAG_PERIODIC);
	if(transfer_timer == NULL)
	{
		Critical_Log("%s create timer failed!\r\n","transfer timer");
	}
	else
		rt_timer_start(transfer_timer);
	return TRANSFER_ERR_NONE;
}
static char log_tcp[512];
static void transfer_input(eth_msg_t event,uint8_t* buff,uint16_t size)
{
	/*考虑存在上位机命令帧被拆分的情况*/
	static uint8_t recv_buff[ETH_RECV_MEM_LENGTH];
	static uint16_t recv_size = 0;
//	rt_base_t it = rt_hw_interrupt_disable();
	transfer_head_t *p_head = (transfer_head_t*)buff;
	transfer_send_node_t* p_node;
	uint16_t crc16 = 0;
	if(event == TCP_RECV && buff != NULL)
	{
		/*打印TCP消息接收*/
		Trace_Log("TCP RECV:");
		log_print_hex(buff,size);
		/*是全帧或者头部帧*/
		if(recv_size == 0 && buff[0] == TRANSFER_HEAD)
		{
			memcpy(recv_buff,buff,size);
			recv_size = size;
		}
		/*非头部的拆分帧*/
		else if(recv_size != 0)
		{
			if(recv_size + size > ETH_RECV_MEM_LENGTH)
			{
				Critical_Log("Recv a illegal tcp frame!\r\n");
				recv_size = 0;
				return;
			}
			memcpy(recv_buff + recv_size,buff,size);
			recv_size += size;
		}
		else
		{
			Trace_Log("Recv a illegal tcp frame!\r\n");
			recv_size = 0;
			return;
		}
		
		p_head = (transfer_head_t*)recv_buff;
		/*如果累计收到一个合理的帧*/
		if(recv_buff[0] == TRANSFER_HEAD &&
//			p_head->length == recv_size &&
			*(recv_buff + p_head->length - 1) == TRANSFER_TAIL)
		{
			Trace_Log("Recv a cmd!\r\n");
		}
		else
		{
			return;
		}
	}
	if(p_head == NULL || recv_size == 0)
		return;
	while(recv_size != 0)
	{
		crc16 = transfer_crc(recv_buff);
		if(crc16 != *((uint16_t*)(recv_buff + p_head->length - sizeof(transfer_tail_t))) )
		{
			Trace_Log("TCP msg id %d crc check failed!",p_head->win);
			return;
		}
		protocol_input(p_head->cmd,recv_buff + sizeof(transfer_head_t),TRANSFER_SEND_DATA_LEN(p_head->length));
		if(p_head->length < recv_size)
		{
			recv_size = recv_size - p_head->length;
			memcpy(recv_buff,recv_buff + p_head->length,recv_size);
		}
		else{
			memset(recv_buff,0,recv_size);
			recv_size = 0;
		}
	}
//	
//	switch(event)
//	{
//		case TCP_CONNECTED:/*每次连接上需要互相发送一个自身的win值帧*/
//			transfer_handle.status = TRANSFER_WAIT_SYN;
//			transfer_output(UPLD_PRODUCT_MSG,transfer_handle.local_win,product_id,strlen(product_id));
//			transfer_handle.send_time = transfer_handle.time_cnt;
//			transfer_handle.local_win++;
//			break;
//		case TCP_DISCONNECT:
//			transfer_handle.status = TRANSFER_DISCONNECT;
//			break;
//		case TCP_RECV:
//		{
//			if(p_head == NULL || recv_size == 0)
//				break;
//			crc16 = transfer_crc(recv_buff);
//			if(crc16 != *((uint16_t*)(recv_buff + p_head->length - sizeof(transfer_tail_t))) )
//			{
//				Trace_Log("TCP msg id %d crc check failed!",p_head->win);
//				break;
//			}
//			switch(p_head->cmd)
//			{
//				/*窗口同步命令*/
//				case CMD_TRANSFER_WIN:
//					if(transfer_handle.status == TRANSFER_WAIT_SYN)
//					{
//						transfer_handle.status = TRANSFER_IDLE;
//						transfer_handle.remote_win = p_head->win + 1;
//					}
//					break;
//				case ACK_CHECK:/*上位机ACK帧*/
//					if(transfer_handle.status == TRANSFER_WAIT_ACK)
//					{
//						if(transfer_handle.local_win == p_head->win)
//						{
//							transfer_handle.status = TRANSFER_IDLE;
//							transfer_handle.err_cnt = 0;
//							transfer_handle.local_win++;
//							if(transfer_handle.p_send_head != NULL)
//							{
//								p_node = transfer_handle.p_send_head->next;
//								rt_mp_free(transfer_handle.p_send_head);
//								transfer_handle.p_send_head = p_node;
//							}
//						}
//						else
//						{
//							Critical_Log("Tcp receive unexpect ack,local win %d,ack win %d",transfer_handle.local_win,p_head->win);
//						}
//					}
//					else
//						Critical_Log("Tcp receive unexpect ack,local win %d,ack win %d",transfer_handle.local_win,p_head->win);
//					break;
//				default:/*上位机命令帧*/
//				{
//					if(p_head->win == transfer_handle.remote_win)
//					{
//						transfer_handle.remote_win++;
//						protocol_input(p_head->cmd,recv_buff + sizeof(transfer_head_t),TRANSFER_SEND_DATA_LEN(p_head->length));
//						transfer_output(ACK_CHECK,p_head->win,NULL,0);
//					}
//					else if(p_head->win < transfer_handle.remote_win)/*一个已经收到的帧*/
//					{
//						transfer_output(ACK_CHECK,p_head->win,NULL,0);
//					}
//					else/*收到的win大于应该的值 报错*/
//						Critical_Log("Tcp receive cmd win err,local win %d,ack win %d",transfer_handle.remote_win,p_head->win);
//					break;
//				}
//			}
//			
//			break;
//		}
//		default:break;
//		
//	}
//	memset(recv_buff,0,recv_size);
//	recv_size = 0;
//	rt_hw_interrupt_enable(it);
}

static void transfer_timer_callback(void* arg)
{
//	return;
	rt_base_t it = rt_hw_interrupt_disable();
//	transfer_handle.time_cnt += TRANSFER_PERIODIIC_INTERVAL;
//	switch(transfer_handle.status)
//	{
//		case TRANSFER_WAIT_SYN:
//			/*同步超时*/
//			if(transfer_handle.time_cnt - transfer_handle.send_time > TRANSFER_ACK_TIMEOUT)
//			{
//				tcp_disconnect(eth_handle.p_tcp_client);
//				transfer_handle.status = TRANSFER_DISCONNECT;
//				transfer_handle.err_cnt = 0;
//			}
//			break;
//		case TRANSFER_WAIT_ACK:
//			if(transfer_handle.time_cnt - transfer_handle.send_time > TRANSFER_ACK_TIMEOUT)
//			{
//				transfer_handle.err_cnt ++;
//				if(transfer_handle.err_cnt > TRANSFER_RESEND_MAX)
//				{
//					transfer_handle.status = TRANSFER_DISCONNECT;
//					transfer_handle.err_cnt = 0;
//					tcp_disconnect(eth_handle.p_tcp_client);
//				}
//				else/*如果发送超时但是不超过三次 则切换到IDLE重发*/
//				{
//					transfer_handle.status = TRANSFER_IDLE;
//				}
//			}
////			transfer_handle.status = TRANSFER_DISCONNECT;
//			break;
//		case TRANSFER_IDLE:
			if(transfer_handle.p_send_head != NULL)
			{
//				transfer_handle.send_time = transfer_handle.time_cnt;
				transfer_output(transfer_handle.p_send_head->cmd,transfer_handle.local_win,
					transfer_handle.p_send_head->buff,transfer_handle.p_send_head->size);
				transfer_send_node_t* p_node = transfer_handle.p_send_head->next;
				rt_mp_free(transfer_handle.p_send_head);
				transfer_handle.p_send_head = p_node;
//				transfer_handle.status = TRANSFER_WAIT_ACK;
			}
//			break;
//		default:break;
//	}
	rt_hw_interrupt_enable(it);
}

static void transfer_output(protocol_cmd_t cmd,uint32_t win,void* buff,uint16_t size)
{
	static uint8_t temp_buff[TRANSFER_SEND_SIZE_MAX];
	rt_base_t it = rt_hw_interrupt_disable();
	if(size + sizeof(transfer_head_t) + sizeof(transfer_tail_t) > TRANSFER_SEND_SIZE_MAX)
	{
		Critical_Log("TCP transfer size %d,max size %d",size,TRANSFER_SEND_SIZE_MAX);
		rt_hw_interrupt_enable(it);
		return;
	}
	transfer_head_t* p_head = (transfer_head_t*)temp_buff;
	p_head->head = TRANSFER_HEAD;
	p_head->win = win;
	p_head->cmd = cmd;
	p_head->length = size + sizeof(transfer_head_t) + sizeof(transfer_tail_t);
	p_head->id = 0;
	memcpy(temp_buff + sizeof(transfer_head_t),buff,size);
	transfer_tail_t* p_tail  =(transfer_tail_t*)(temp_buff + size + sizeof(transfer_head_t));
	p_tail->modbus_crc = transfer_crc(temp_buff);
	p_tail->tail = TRANSFER_TAIL;
	eth_tcp_write(temp_buff,p_head->length);
	rt_hw_interrupt_enable(it);
}
transfer_err_t tcp_transfer_push(protocol_cmd_t cmd,void* buff,uint16_t size)
{
	ASSERT(size < (TRANSFER_SEND_SIZE_MAX - sizeof(transfer_head_t) - sizeof(transfer_tail_t)));
	rt_base_t it = rt_hw_interrupt_disable();
	transfer_send_node_t* p_node;
	transfer_send_node_t* p_temp;
	transfer_send_node_t* p_new = rt_mp_alloc(&transfer_handle.transfer_send_mem,RT_WAITING_NO);
	if(p_new == NULL)/*内存申请失败，可能是网络传输堵塞，酌情删除部分内容 比如呼吸包*/
	{
		if(transfer_handle.p_send_head == NULL)
		{
			Error_Log("Unexpect fatal err!");
			rt_hw_interrupt_enable(it);
			while(1);
		}
		/*网络堵塞时删除呼吸包*/
//		p_node = transfer_handle.p_send_head;
//		while(p_node->next != NULL)
//		{
//			if(p_node->next->cmd == UPLD_PERIOD)
//			{
//				p_temp = p_node->next;
//				p_node->next = p_temp->next;
//				rt_mp_free(p_temp);
//				continue;
//			}
//			else
//				p_node = p_node->next;
//		}
		/*当前连接已经中断那么将最早的一个帧删除*/
		if(transfer_handle.status == TRANSFER_DISCONNECT)
		{
			p_node = transfer_handle.p_send_head;
			transfer_handle.p_send_head = transfer_handle.p_send_head->next;
			rt_mp_free(p_node);
		}
		else/*其他情况下那就是传输速度不行了 不管了*/
		{
		}
		/*再次申请*/
		p_new = rt_mp_alloc(&transfer_handle.transfer_send_mem,RT_WAITING_NO);
	}
	if(p_new == NULL)
	{
		Critical_Log("Transfer blocked,cmd 0x%X abandoned!",cmd);
		rt_hw_interrupt_enable(it);
		return TRANSFER_ERR_BLOCKED;
	}
	
	p_new->cmd = cmd;
	p_new->size = size;
	p_new->next = NULL;
	if(buff != NULL && size > 0)
		memcpy(p_new->buff,buff,size);
	p_node = transfer_handle.p_send_head;
	if(transfer_handle.p_send_head == NULL)
		transfer_handle.p_send_head = p_new;
	else
	{
		while(p_node->next != NULL)
		{
			p_node = p_node->next;
		}
		p_node->next = p_new;
	}
	rt_hw_interrupt_enable(it);
}
transfer_err_t tcp_err_push(product_err_code_t err_code,const char * fmt,...)
{
//	char* buff = malloc(TRANSFER_SEND_SIZE_MAX);
//	if(buff == NULL)
//	{
//		Critical_Log("malloc failed!\r\n");
//		return TRANSFER_ERR_NONE;
//	}
//	memset(buff,0,TRANSFER_SEND_SIZE_MAX);
//	rt_base_t it = rt_hw_interrupt_disable();
//	va_list args;
//	va_start(args, fmt);

//	char *pc = buff;
//	uint16_t len = 0;
//	uint16_t temp_len;
//	
//	*((uint32_t*)buff) = err_code;
//	len += sizeof(uint32_t);
//	pc = pc + len;
//	
//	len += vsnprintf(pc,LOG_TTY_BUF_SIZE,fmt,args);
//	va_end(args);
//	if(len > TRANSFER_SEND_SIZE_MAX)
//	{
//		Critical_Log("Error log oversize!\r\n");
//	}
//	else
//	{
//		Error_Log("0x%08X:%s;\r\n",*(uint32_t*)buff,buff+4);
//	}
//	rt_hw_interrupt_enable(it);
//	tcp_transfer_push(UPLD_ERRCODE,buff,len);
//	free(buff);
	return TRANSFER_ERR_NONE;
}
static uint16_t transfer_crc(uint8_t* buff)
{
	if(NULL == buff)
		return 0;
	transfer_head_t *p_head = (transfer_head_t*)buff;
	return ModBusCRC((uint8_t*)&p_head->win,p_head->length - 4);
}